5.01. Инструменты и фреймворки
Инструменты и фреймворки
Архитектура крупных JavaScript-приложений
Современные JavaScript‑приложения — особенно CRM, BPM, ERP и другие enterprise‑системы — достигают значительных масштабов: сотни тысяч строк кода, десятки тысяч активных пользователей, интеграции с внешними сервисами и внутренними подсистемами. Архитектурная устойчивость таких систем опирается на принцип модульности: разложение приложения на логически и технически обособленные части, каждая из которых отвечает за чётко определённую область функциональности.
Соответственно, в крупном приложении добавляются принципы:
- Модульность — разделение кода на автономные, переиспользуемые и тестируемые части.
- Ленивая загрузка (lazy loading) — загрузка кода по требованию, а не единовременно при старте приложения.
- Безопасное взаимодействие между компонентами — минимизация связности, контроль над интерфейсами.
- Управление зависимостями — явное декларирование и разрешение зависимостей между модулями.
- Поддержка версионной совместимости — возможность одновременной работы различных версий библиотек.
Эти принципы реализуются через системы модулей, которые определяют, как код организован, как он загружается и как происходит обмен данными между частями приложения.
Модуль — это автономный фрагмент кода, который инкапсулирует определённую функциональность, имеет собственное пространство имён и экспортирует ограниченный интерфейс для использования другими частями приложения. Модуль скрывает свою внутреннюю реализацию и предоставляет только те сущности, которые явно объявлены как публичные.
Преимущества модульного подхода:
- Уменьшение глобального загрязнения.
- Повторное использование кода.
- Легкость тестирования и замены реализаций.
- Возможность независимой разработки и развёртывания.
Внутри модуля возможна любая организация кода: классы, функции, константы, конфигурации, шаблоны, стили. Однако для сохранения модульности необходимо соблюдать одно правило: всё, что требуется внешнему коду, должно быть явно экспортировано; всё остальное остаётся приватным для модуля.
Пример структуры модуля:
// modules/user/profile.js
const apiUrl = '/api/v2/users'; // приватная константа
function fetchUserProfile(id) {
return fetch(`${apiUrl}/${id}`).then(r => r.json());
}
function formatDisplayName(user) {
return `${user.lastName} ${user.firstName}`;
}
export { fetchUserProfile, formatDisplayName };
Здесь apiUrl и логика fetchUserProfile инкапсулированы. Внешний код может использовать только то, что указано в export. Инкапсуляция обеспечивает внутреннюю согласованность модуля и минимизирует побочные эффекты при изменении его реализации.
Модули могут быть атомарными (один файл — один модуль) или составными (модуль представлен директорией с index.js, агрегирующим внутренние подмодули). Такая гибкость позволяет выстраивать иерархию: от простых утилит до сложных подсистем (например, модуль «Управление документооборотом» может включать подмодули «Шаблоны», «Маршруты», «Подписи»).
Библиотека — это набор модулей, предоставляющий готовую функциональность: работу с датами, валидацию форм, рендеринг интерфейсов, маршрутизацию, HTTP‑клиент и так далее. В отличие от прикладных модулей, библиотеки разрабатываются с расчётом на многократное использование, независимо от конкретного проекта.
Библиотеки встраиваются в приложение через менеджеры зависимостей (npm, pnpm, yarn), где каждая версия фиксируется в манифесте (package.json). Это позволяет одновременно использовать несколько версий одной библиотеки (в редких случаях — через алиасы или отдельные сборки), но в типичной практике приложение фиксирует одну версию каждой внешней зависимости.
Подключение модуля происходит через import. В режиме ES‑модулей импорт статичен: на этапе лексического анализа кода определяется, какие модули нужны, и строится граф зависимостей. Этот подход обеспечивает детерминированный порядок инициализации и позволяет инструментам сборки проводить глубокий анализ.
import { fetchUserProfile } from './modules/user/profile.js';
import { formatDateTime } from 'date-fns';
Отключение модуля — архитектурное решение: модуль перестаёт быть частью графа зависимостей. В статической сборке это достигается исключением import или условным импортом с участием инструментов (например, динамический импорт с проверкой флага). В рантайме отключение реализуется через динамическую загрузку и управление жизненным циклом.
Если модуль не используется ни в одном месте приложения, он может быть полностью исключён из итоговой сборки — механизм, известный как tree shaking. Он работает при соблюдении трёх условий:
- Используется формат ES‑модулей (не CommonJS).
- Модуль не содержит побочных эффектов при импорте.
- Сборщик поддерживает статический анализ (Rollup, Webpack ≥5, Vite).
В крупных системах отключение ненужных модулей особенно важно при поддержке нескольких вариантов сборки: например, одна версия для внутреннего админ‑интерфейса, другая — для внешнего портала клиентов. Тогда каждая сборка включает только те модули, которые действительно требуются в данном контексте.
Модули делятся на обязательные и необязательные по критерию жизненно важности для старта приложения.
Обязательные модули — ядро, без которого приложение не может функционировать. К ним относятся: механизм маршрутизации, базовый UI‑фреймворк (например, React с его reconciler’ом), глобальный store, сервисы аутентификации и авторизации. Эти модули загружаются синхронно на этапе инициализации.
Необязательные модули — функциональность, активируемая по требованию: отчёты, аналитика, настройки интеграций, редко используемые формы. Такие модули подключаются динамически, что снижает объём первоначальной загрузки и ускоряет время отклика.
Динамический импорт в JavaScript реализуется через import() — функцию, возвращающую промис:
async function loadReportingModule() {
const { generateReport } = await import('./modules/reporting/engine.js');
return generateReport;
}
Сборщики преобразуют такой вызов в отдельный чанк (файл), который загружается только при выполнении условия (например, при переходе в раздел «Отчёты»). Это — основа стратегии code splitting.
При проектировании системы важно чётко разделять обязательные и необязательные модули уже на этапе архитектурного анализа. Карта использования функциональности (usage map), построенная по логам или аналитике, помогает определить, какие модули следует динамизировать.
Зависимости и безопасное взаимодействие
Взаимодействие между модулями происходит через их публичные интерфейсы. Безопасность этого взаимодействия обеспечивается несколькими уровнями контроля:
1. Статический контроль типов (при использовании TypeScript)
TypeScript проверяет совместимость сигнатур при компиляции. Если модуль A ожидает функцию вида (id: number) => Promise<User>, а модуль B предоставляет (id: string) => Promise<User>, ошибка будет обнаружена на этапе сборки.
Это особенно ценно при рефакторинге: изменение интерфейса одного модуля немедленно обнаруживается в местах его использования.
2. Контракты на уровне данных
Интерфейсы модулей часто реализуются через DTO (Data Transfer Objects) — простые объекты без методов, передаваемые между слоями. Для валидации таких объектов применяются схемы: zod, io-ts, yup. Проверка схемы происходит при входе в модуль:
import { UserProfileSchema } from './schemas/user';
function processUserProfile(raw: unknown) {
const validated = UserProfileSchema.parse(raw);
// дальше — работа только с validated, гарантированно соответствующим ожиданиям
}
Такой подход локализует ошибки: проблема возникает в точке входа, а не где‑то глубоко внутри логики.
3. Изоляция побочных эффектов
Хорошо спроектированный модуль не вызывает побочные эффекты за пределами своего контекста без явного согласия. Например, модуль не подписывается на глобальные события, не изменяет DOM вне своей области ответственности, не записывает в localStorage без параметризации.
В случаях, где побочный эффект неизбежен (например, HTTP‑запрос), он инкапсулируется в специализированный адаптер — сервис с чётким интерфейсом (HttpClient, EventBus, StorageGateway). Модуль зависит не от реализации, а от абстракции, что упрощает тестирование и подмену реализаций.
4. Версионирование интерфейсов
Крупные системы живут годами, и за это время интерфейсы модулей могут эволюционировать. Чтобы избежать нарушения совместимости, применяются практики:
- Семантическое версионирование (SemVer) внешних библиотек.
- Интерфейсные версии (API versioning) для внутренних модулей:
export { v1 as default } from './v1'; export { v2 } from './v2';. - Обратная совместимость на уровне конфигурации: новые параметры добавляются необязательно, старые сохраняются с устаревшим статусом (
@deprecatedв JSDoc).
Когда модуль A зависит от модуля B, в манифесте проекта (или в метаинформации сборки) фиксируется диапазон допустимых версий B. Инструменты вроде npm outdated или pnpm audit отслеживают расхождения.
Совместимость между версиями библиотек
Совместимость — не абстракция, а практический результат управления зависимостями. В JavaScript‑экосистеме она обеспечивается через:
- Плоскую структуру зависимостей (flat node_modules) — менеджеры вроде pnpm или Yarn Plug’n’Play позволяют избежать дублирования одних и тех же библиотек в разных версиях, тем самым устраняя конфликты.
- Алиасы зависимостей — в
package.jsonможно явно указать, какую версию библиотеки использовать, даже если другие пакеты требуют иную:
{
"dependencies": {
"react": "18.2.0"
},
"resolutions": {
"react": "18.2.0"
}
}
- Полифилы и адаптеры — если новая версия библиотеки убрала метод, а старый код на него завязан, создаётся временный адаптер, восстанавливающий совместимость до полной модернизации.
Критически важно избегать ситуаций, когда две части приложения используют разные экземпляры одной библиотеки в несовместимых версиях — особенно это касается библиотек, хранящих глобальное состояние (например, React). В таких случаях возникают трудноуловимые ошибки: дублирование контекстов, рассинхронизация хуков, конфликты подписок.
Для предотвращения этого применяется стратегия единый экземпляр (single instance): сборщик настраивается так, чтобы все импорты react разрешались в один файл. В Webpack это достигается через resolve.alias или externals.
Системы модулей (AMD, CommonJS, ES Modules).
AMD (Asynchronous Module Definition) — это спецификация, определяющая способ организации модулей с поддержкой асинхронной загрузки. Она была разработана с учётом особенностей браузерного окружения, где сетевая задержка при загрузке файлов является ключевым фактором производительности.
AMD позволяет определять модули таким образом, что их зависимости загружаются асинхронно, без блокировки выполнения основного потока. Это критично для больших приложений, где загрузка всех модулей сразу привела бы к долгому времени запуска.
Две основные функции в AMD - define и require.
define(id?, dependencies, factory) — используется для определения модуля.
Здесь:
- id — необязательный идентификатор модуля.
- dependencies — массив строк, указывающих на другие модули, от которых зависит текущий.
- factory — функция-конструктор, которая будет вызвана после загрузки всех зависимостей. Аргументы функции соответствуют загруженным модулям в порядке объявления.
define(['dependency1', 'dependency2'], function(dep1, dep2) {
// Логика модуля
return {
doSomething: function() {
dep1.action();
dep2.log('Module is ready');
}
};
});
require(dependencies, callback) — используется для загрузки и использования модулей в произвольном месте кода.
require(['moduleA', 'moduleB'], function(A, B) {
A.doSomething();
B.render();
});
Функция require гарантирует, что все перечисленные зависимости будут загружены до вызова колбэка.
AMD имеет особенности:
- Поддержка асинхронной загрузки — модули могут быть загружены по сети динамически.
- Гибкость в динамическом подключении — можно загружать модули «на лету», например, при переходе по маршруту.
- Поддержка не-JavaScript ресурсов — некоторые реализации AMD (например, RequireJS) позволяют загружать CSS, шаблоны, JSON и другие типы файлов через плагины.
AMD был особенно популярен в период до массового внедрения ES6 и ESM.
Он широко использовался в enterprise-фреймворках:
- Dojo Toolkit
- Ext JS
- Ранние версии AngularJS (через адаптеры)
- SAPUI5
- Creatio (ранее BPM'online) и BPMSoft.
RequireJS — одна из наиболее известных реализаций AMD. Она предоставляет динамическую загрузку модулей, управление графом зависимостей, оптимизацию сборки с помощью утилиты r.js, которая объединяет модули в единые файлы для production и поддержку конфигурации путей, алиасов и условной загрузки.
Несмотря на то, что RequireJS утратил доминирующую роль в новых проектах, он остаётся в legacy-системах, особенно в корпоративных решениях, где миграция на современные стандарты сопряжена со значительными рисками.
CommonJS — это инициатива сообщества, направленная на стандартизацию JavaScript вне браузера, в первую очередь для серверной среды.
CommonJS использует синхронную модель загрузки модулей через функцию require. Каждый файл представляет собой отдельный модуль с собственной областью видимости. Экспорт осуществляется через объект module.exports, импорт — через require.
Пример:
// math.js
function add(a, b) {
return a + b;
}
module.exports = { add };
// app.js
const math = require('./math');
console.log(math.add(2, 3));
Особенности CommonJS:
- Синхронная загрузка — require блокирует выполнение до завершения загрузки и выполнения модуля.
- Подходит для Node.js, где файлы доступны локально на диске и задержки минимальны.
- Не поддерживается нативно в браузерах — требует сборщика (Webpack, Browserify и др.) для преобразования в браузерный формат.
- Прост в использовании, хорошо работает с файловой системой.
CommonJS имеет и ограничения, к примеру, он непригоден для браузера без инструментов сборки из-за синхронной природы, не поддерживает динамическую загрузку «из коробки» (хотя современные сборщики эмулируют её) и может приводить к большим bundle-файлам при отсутствии tree-shaking. CommonJS остаётся стандартом де-факто в Node.js, хотя начиная с Node.js 14+ активно развивается поддержка ESM.
ES Modules (ECMAScript Modules, ESM) — это официальный стандарт модульности, принятый в спецификацию ECMAScript (ES6, 2015). Он представляет собой декларативный подход к модульности с поддержкой как статического, так и динамического импорта. Синтаксис включает два основных варианта:
- import — для импорта сущностей.
- export — для экспорта.
// utils.js
export function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
export const MAX_ATTEMPTS = 3;
// main.js
import { validateEmail, MAX_ATTEMPTS } from './utils.js';
if (validateEmail('user@example.com')) {
console.log(`Attempts allowed: ${MAX_ATTEMPTS}`);
}
Также поддерживается дефолтный экспорт:
// logger.js
export default function log(message) {
console.log('[LOG]', message);
}
// main.js
import logger from './logger.js';
logger('Hello world');
ESM поддерживает динамический импорт через import() — функцию, возвращающую Promise. Это позволяет загружать модули по требованию. Это ключевой механизм для ленивой загрузки в современных SPA:
button.addEventListener('click', async () => {
const module = await import('./heavyComponent.js');
module.render();
});
Какие же особенности есть у ESM?
- Статическая структура — анализ зависимостей возможен на этапе сборки (enables tree-shaking).
- Асинхронная загрузка — реализуется через import() и поддерживается браузерами.
- Нативная поддержка — в современных браузерах и Node.js (с флагом .mjs или "type": "module" в package.json).
- Однократная загрузка — модуль кэшируется; повторные импорты возвращают тот же экземпляр.
- Жёсткие правила относительных/абсолютных путей — в браузере требуется полное имя файла с расширением (например, ./utils.js, а не ./utils).
Преимущества перед предыдущими системами:
- Единый стандарт, поддерживаемый движками.
- Интеграция с современными инструментами (Vite, Webpack, Rollup).
- Поддержка tree-shaking, code splitting, HMR.
- Совместимость с TypeScript и JSX.
Переход с CommonJS на ESM в Node.js потребовал решения проблемы двойной поддержки. Для этого используются расширения .cjs/.mjs, поле "type": "module" в package.json и условные exports ("exports" в package.json).
Архитектура крупных JavaScript-приложений невозможна без чёткой системы модулей. Выбор между AMD, CommonJS и ES Modules определяется контекстом: целевой средой, требованиями к производительности, размером команды и историческим багажом проекта.
Если вам придётся работать с JS, то скорее всего не на ванильном, а на каком-то из вышеперечисленных вариантов. К примеру, это может быть разработка систем на платформе Creatio, которая как раз использует AMD.
Песочница (Sandbox) и шина сообщений
В сложных приложениях, где множество независимых модулей (например, от разных команд), нельзя допускать прямого доступа одного модуля к другому. Решение — песочница.
Что такое песочница? Это изолированная среда выполнения для модулей.
Модули не видят глобальных переменных и не могут напрямую вызывать друг друга, а взаимодействие происходит через центральную шину сообщений (event bus).
Как это работает?
// Модуль отправляет сообщение
sandbox.publish('user:login', { userId: 123 });
// Другой модуль подписывается
sandbox.subscribe('user:login', function(data) {
console.log('Пользователь вошёл:', data.userId);
});
Преимущества:
- Изоляция: один модуль не может сломать другой.
- Гибкость: модули можно добавлять/удалять без переписывания кода.
- Безопасность: предотвращается загрязнение глобальной области.
- Поддержка микроприложений и плагинов.
Такой подход используется в:
-
Creatio / BPMSoft. Например, в Creatio можно представить, что:
- Ядро предоставляет песочницу и шину сообщений.
- Каждый модуль — это AMD-модуль, загружаемый по требованию.
- Внешние библиотеки (Angular, Ext JS) подключаются как зависимости.
-
Ext JS + Sencha Cmd. Ext JS активно использовал RequireJS и AMD до перехода на современные сборщики. MVC/MVVM архитектура хорошо сочетается с шиной сообщений.
-
Backbone.js с Marionette
Angular, Vue, React не используют такой подход - там ES Modules.
Сегодня вместо AMD и песочниц используются:
- ES Modules + Dynamic import() — для динамической загрузки.
- Micro-Frontends — архитектура, где каждая часть приложения — независимое приложение.
- Module Federation (Webpack 5) — позволяет объединять модули из разных приложений.
- Web Workers / iframes — для настоящей изоляции.
В архитектуре крупных JavaScript-приложений, особенно в условиях мультикомандной разработки, высокой динамики изменений и необходимости поддержки долгосрочной совместимости, критически важным становится управление взаимодействием между модулями. Прямые зависимости между компонентами приводят к повышению связанности, затрудняют тестирование, усложняют замену реализаций и увеличивают риски регрессии.
Для решения этих проблем применяется подход, основанный на изоляции модулей и опосредованном взаимодействии через централизованные механизмы. Два ключевых элемента такого подхода — песочница (sandbox) и шина сообщений (event bus).
Песочница (sandbox) — это абстрактная среда выполнения, предоставляемая каждому модулю при его инициализации. Она выступает в роли посредника между модулем и остальной системой, ограничивая прямой доступ к глобальному окружению, другим модулям или внутренним механизмам ядра.
Цель песочницы — обеспечить контролируемую и безопасную коммуникацию, исключив возможность несанкционированного вмешательства в работу других компонентов.
Основные характеристики песочницы:
- Изоляция: модуль не имеет прямого доступа к объектам других модулей.
- Ограниченный API: модуль может использовать только те методы, которые явно предоставлены песочницей.
- Единая точка входа/выхода: весь обмен данными проходит через строго определённые интерфейсы.
- Контекст исполнения: песочница может инжектировать зависимости, управлять жизненным циклом модуля и перехватывать ошибки.
Таким образом, песочница представляет собой программный слой, реализующий политику безопасности и взаимодействия.
При отсутствии прямых ссылок между модулями возникает необходимость в альтернативном способе обмена информацией. Этой функцией служит шина сообщений (message bus, event bus) — централизованный механизм маршрутизации событий.
В шине сообщений, модули не вызывают друг друга напрямую. Вместо этого они:
- Публикуют события — отправляют сообщение в шину с указанием типа события и полезной нагрузки.
- Подписываются на события — объявляют интерес к определённым типам сообщений и регистрируют обработчики.
// Модуль A: публикует событие
sandbox.publish('user:login', { userId: 123 });
// Модуль B: подписывается на событие
sandbox.subscribe('user:login', function(data) {
console.log('Пользователь вошёл:', data.userId);
});
Система шины сообщений гарантирует, что все подписчики получат уведомление, если событие произошло, независимо от времени их инициализации (при условии, что подписка была зарегистрирована до момента публикации).
Типы событий:
- События домена — отражают бизнес-события (order:created, user:updated).
- События UI — связаны с интерфейсом (modal:open, form:submit).
- Системные события — управляют жизненным циклом (module:loaded, app:ready).
Причём эти события уже не относятся к DOM-событиям вроде кликов мыши, нет. Это полноценные действия в других модулях.
Такая архитектура естественно поддерживает модели, где функциональность расширяется за счёт внешних модулей, в том числе сторонних разработчиков. Можно динамически добавлять, удалять или заменять модули без изменения кода других компонентов. Например, плагин может просто подписаться на событие ядра и расширить его функциональность. Модули не зависят друг от друга ни на уровне кода, ни на уровне времени загрузки. Это позволяет разрабатывать, тестировать и развёртывать модули независимо. Песочница предотвращает загрязнение глобального пространства имён, блокирует прямой доступ к внутренним структурам и минимизирует влияние ошибок одного модуля на другие. Поведение модуля можно проверять, имитируя события и анализируя публикуемые ответы, без необходимости запуска всей системы.
Одним из характерных примеров применения песочницы и шины сообщений является платформа Creatio (ранее BPM'online), ориентированная на enterprise-сегмент и построенная на основе AMD и собственной архитектуры модульности.
Архитектурные особенности:
- Ядро системы предоставляет экземпляр песочницы каждому загружаемому модулю.
- Все модули являются AMD-модулями, загружаемыми по требованию.
- Взаимодействие между модулями осуществляется исключительно через sandbox.publish() и sandbox.subscribe().
- Внешние библиотеки (например, Ext JS) подключаются как зависимости через AMD, но их использование контролируется через API песочницы.
Такой подход позволяет настраивать поведение CRM/BPM-системы без изменения ядра, разрабатывать модули независимыми командами и обеспечивать обратную совместимость между версиями.
Ранние версии фреймворка Ext JS активно использовали RequireJS и AMD для организации модульности. Архитектура MVC/MVVM, заложенная в Ext JS, хорошо сочетается с шиной сообщений: контроллеры могут обмениваться данными через глобальный event bus, минимизируя прямые связи между представлениями и моделями. Sencha Cmd — инструмент сборки — позволял управлять зависимостями, оптимизировать загрузку и создавать изолированные модули, что соответствовало принципам песочницы.
Фреймворк Backbone.js, хотя и не предусматривает шины сообщений «из коробки», допускает её реализацию через Backbone.Events. Библиотека Marionette расширяет этот подход, предоставляя EventAggregator — централизованный менеджер событий, выполняющий функции шины.
В ранних моделях микрофронтендов, особенно в гибридных SPA, где части приложения разрабатываются разными командами и интегрируются в runtime, используется шина сообщений для координации. Например, один микрофронтенд может уведомлять другой о смене пользователя или состоянии авторизации.
Хотя модель песочницы и шины сообщений остаётся актуальной в legacy-системах, в современных архитектурах она постепенно вытесняется более масштабируемыми и стандартизированными решениями. С появлением нативной поддержки ES Modules и динамического импорта (import()), необходимость в AMD и внешних системах загрузки отпала. Теперь модули могут загружаться по требованию без дополнительных библиотек:
button.addEventListener('click', async () => {
const { renderChart } = await import('./charts.js');
renderChart(data);
});
Это решает задачу ленивой загрузки, но не обеспечивает изоляции на уровне выполнения.
Архитектура микрофронтендов предполагает, что каждая часть приложения — это самостоятельное приложение со своей технологической стеком, CI/CD и командой. Взаимодействие между ними может происходить через Custom Events, Shared libraries, State managers или ту же шину сообщений, но на уровне окна (window.postMessage).
Module Federation — механизм, позволяющий объединять модули из разных сборок Webpack в единую runtime-среду. Он даёт возможность импортировать модули «на лету» из удалённой сборки, совместно использовать библиотеки, строить распределённые приложения без централизованной сборки. Module Federation можно рассматривать как эволюцию идеи песочницы: модули остаются независимыми, но получают контролируемый доступ к функциональности друг друга.
Для достижения настоящей изоляции, когда модуль не может повлиять на глобальное состояние, используются:
- Web Workers — выполнение кода в отдельном потоке без доступа к DOM.
- iframes — изоляция на уровне документа, с собственным window, document, localStorage.
Такие подходы применяются, например, в платформах, принимающих пользовательские скрипты (виджеты, плагины), где безопасность является первостепенной.
Общее о фреймворках и транслируемых языках
Прочие транслируемые языки, подобные TypeScript - CoffeeScript, Flow, Dart, Brython.
Ещё есть ActionScript – язык для Flash-приложений. Сейчас его уже редко встретить из-за того, что устарел. Использовался для анимаций, игр, веб-приложений.
Фреймворки JavaScript.
Фронтенд:
| Фреймворк | Описание |
|---|---|
| React | Библиотека для UI. Создана Facebook (Meta), работает с компонентами — маленькими частями интерфейса. Не навязывает архитектуру, но требует больше самостоятельности. Часто используется с ReactDOM, React Router, Redux, Next.js react.dev metanit.com/web/react cheatsheets.zip/react |
| Vue | Прогрессивный фреймворк. Легко внедряется в существующий проект, весьма простой и понятный для новичков. Используется с Vue Router, Vuex, Nuxt.js vuejs.org metanit.com/web/vue cheatsheets.zip/vue |
| Angular | Фреймворк от Google. Написан на TypeScript, имеет чёткую структуру: компоненты, сервисы, директивы, модули. angular.dev metanit.com/web/angular2 |
| Svelte | Компилируется в чистый JavaScript, не использует виртуальный DOM. Логика, разметка и стили объединены в одном файле компонента. svelte.dev |
| Ext JS | Extended JavaScript (Sencha Ext JS), включает виджеты, графики, древовидные структуры и меню для создания сложных интерфейсов с поддержкой MVC-шаблона с разделением логики приложения, данных и представлений. www.sencha.com/products/extjs metanit.com/web/extjs |
Фронтенд-фреймворки помогают создавать динамические интерфейсы и управлять состоянием приложения.
Бэкенд (Node.js):
Официальный сайт Node.js - https://nodejs.org/
| Фреймворк | Описание |
|---|---|
| Express | Минималистичный фреймворк expressjs.com |
| NestJS | Фреймворк с TypeScript nestjs.com |
| Fastify | Альтернатива Express (высокая производительность) fastify.dev |
Фреймворк — это набор готовых решений и структура, которые помогают разрабатывать приложения быстрее, проще и с лучшими практиками.
Фреймворк — это заранее подготовленная структура кода , которая предоставляет готовые компоненты, архитектурные шаблоны, правила организации проекта и расширяемость. В отличие от библиотек, где мы решаем, когда и как использовать функции, во фреймворке всё наоборот: фреймворк управляет нашим кодом . То есть мы подстраиваемся под его правила.
Работа с фреймворком подразумевает:
- Импорт модулей (к примеру,
import React from 'react';). - Использование специфичных конструкций, к примеру
// React
function App() {
return <h1>Привет, React!</h1>;
}
// Vue
export default {
template: `<h1>Привет, Vue!</h1>`
}
// NestJS
@Controller('cats')
class CatsController {}
- Следование определённой структуре проекта. Например, в Angular или NestJS у нас будут папки components, services, modules и так далее.
- Использование CLI (интерфейс командной строки) - большинство фреймворков предоставляют CLI-инструменты:
- ng new my-app — Angular
- create-react-app my-app — React
- nest new my-project — NestJS
- npm create vue@latest — Vue
Эти команды создают уже подготовленную структуру проекта с нужными зависимостями и конфигами.
Среди фреймворков можно также выделить Electron (хотя это скорее среда разработки) с открытым исходным кодом, который позволяет создавать десктоп-приложения с использованием веб-технологий HTML, CSS и JavaScript. Он основан на Node.js и движке Chromium. Приложения на Electron можно запускать на Windows, macOS, Linux, можно работать с файловой системой, сетью, процессами (благодаря Node.js).
На Electron работают Visual Studio Code, Slack, Discord, Postman, Atom, Trello Desktop, GitHub Desktop - то есть, среда довольно функциональная и позволяет формировать GUI. У Electron есть и альтернативы вроде Tauri (для Rust), NW.js, Flutter Desktop (Dart), React Native.
Минимальное приложение на таком движке имеет package.json, main.js, index.html.
jQuery
jQuery — это популярная JavaScript-библиотека с открытым исходным кодом, которая упрощает работу с DOM (Document Object Model), обработку событий, анимацию и взаимодействие с сервером через AJAX. Она была создана в 2006 году Джоном Резигом и с тех пор стала одной из самых используемых библиотек на стороне клиента.
jQuery позволяет легко находить элементы на странице и манипулировать ими:
// Пример: изменить текст всех параграфов
$('p').text('Новый текст');
Легко добавлять обработчики событий:
// Пример: обработка клика по кнопке
$('#myButton').click(function() {
alert('Кнопка нажата!');
});
Упрощает выполнение асинхронных запросов к серверу:
$.ajax({
url: 'https://api.example.com/data',
success: function(response) {
console.log('Данные получены:', response);
}
});
Встроенные методы для анимации:
// Скрыть элемент с анимацией
$('#box').fadeOut(1000);
// Показать элемент
$('#box').fadeIn(500);
jQuery также имеет большое количество готовых плагинов для расширения возможностей, включая формы валидации, слайдеры, таблицы с фильтрацией, модальные окна.
Официальный сайт - https://jquery.com/
Чит-лист - https://cheatsheets.zip/jquery